﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Cryptography;
using System.Text;
using System.Web.Security;

using System.Configuration;
using System.Data.SqlClient;
using System.Data;
using System.Globalization;
using System.IO;
using System.Web.UI.WebControls;
using System.Net;



namespace Anuntiomatic.Server
{
    public class BasePage : System.Web.UI.Page
    {
        #region Properties
        private DBDataContext db = new DBDataContext();
        public DBDataContext DB { get { return db; } }
        public int? UserID
        {
            get
            {
                if (string.IsNullOrEmpty(User.Identity.Name))
                {
                    return null;
                }
                else
                {
                    return int.Parse(User.Identity.Name);
                }
            }
            set
            {
                if (value == null)
                {
                    FormsAuthentication.SignOut();
                }
                else
                {
                    FormsAuthentication.SetAuthCookie(value.ToString(), false);
                }
            }
        }

        public SysUser CurUser
        {
            get
            {
                if (UserID == null)
                {
                    return null;
                }
                else
                {
                    return SysUser.GetByID(UserID.Value);
                }
            }
        }
        
        public string AccessDeniedURL
        {
            get { return ResolveUrl(ConfigurationManager.AppSettings["AccessDeniedURL"]); }
        }
        public string DefaultURL
        {
            get { return ResolveUrl(ConfigurationManager.AppSettings["DefaultURL"]); }
        }
        public string LoginURL
        {
            get { return ResolveUrl(ConfigurationManager.AppSettings["LoginURL"]); }
        }
        public string ReturnURL
        {
            get
            {
                string returnURL = (string)Session[SESSION.RETURN_URL];
                if (returnURL == null || returnURL == AccessDeniedURL || returnURL == LoginURL) return DefaultURL;
                return returnURL;
            }
            set
            {
                if (Session[SESSION.RETURN_URL] == null)
                    Session.Add(SESSION.RETURN_URL, value);
                else
                    Session[SESSION.RETURN_URL] = value;
            }
        }
        public string ChangePasswordURL
        {
            get { return ResolveUrl(ConfigurationManager.AppSettings["ChangePasswordURL"]); }
        }
        public int PageSize
        {
            get
            {
                if (Session[SESSION.PageSize] == null) return 50;
                return (int)Session[SESSION.PageSize];
            }
            set
            {
                if (Session[SESSION.PageSize] == null)
                    Session.Add(SESSION.PageSize, value);
                else
                    Session[SESSION.PageSize] = value;
            }

        }
        public IFormatProvider DateTimeFormat
        {
            get
            {
                return CultureInfo.CreateSpecificCulture(ConfigurationManager.AppSettings["CultureInfo"]);
            }
        }
        #endregion
       
        protected override void OnInit(EventArgs e)
        {
            try
            {
                if (!IsPostBack)
                {
                    if (!HasRole())
                        RedirectToPage(AccessDeniedURL);
                    if (RequiredChangePassword())
                    {
                        RedirectToPage(ChangePasswordURL);
                    }
                }
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            base.OnInit(e);
        }

        protected override void OnLoad(EventArgs e)
        {
            if (RequiredLogin())
            {
                if (Session.IsNewSession)
                    Session.Timeout = 60;
                ReturnURL = Request.RawUrl;
                RedirectToPage(LoginURL);
                return;
            }
            base.OnLoad(e);
        }

        private bool IsRefresh()
        {
            bool isRefresh = false;
            if (!IsPostBack)
            {
                isRefresh = false;
                Session[SESSION.PostID] = (int)0;
                ViewState[SESSION.PostID] = (int)0;
            }
            else
            {
                if (Session[SESSION.PostID] != null && ViewState[SESSION.PostID] != null)
                {
                    if ((int)Session[SESSION.PostID] == (int)ViewState[SESSION.PostID])
                    {
                        Session[SESSION.PostID] = (int)Session[SESSION.PostID] + 1;
                        ViewState[SESSION.PostID] = (int)Session[SESSION.PostID];
                        isRefresh = false;
                    }
                    else
                    {
                        ViewState[SESSION.PostID] = (int)Session[SESSION.PostID];
                        isRefresh = true;
                    }
                }
                else
                    isRefresh = false;
            }
            return isRefresh;
        }

        protected virtual bool RequiredLogin()
        {
            if (UserID == null)
                return true;
            return false;
        }

        protected virtual bool RequiredChangePassword()
        {
            if (UserID == null)
                return false;
            if (CurUser.RequiredChangePassword == false)
                return false;
            return true;
        }
        
        #region Utils
        /// <summary>
        /// Điều hướng trang
        /// </summary>
        /// <param name="urlPage">Địa chỉ điều hướng</param>
        protected void RedirectToPage(string urlPage)
        {
            Response.Redirect(urlPage, false);
        }

        protected string GetQueryString(string parameter)
        {
            if (Request.QueryString[parameter] == null) return string.Empty;
            return (string)Request.QueryString[parameter];
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        public void ShowMessageBox(string message)
        {
            string script = string.Format(@"jAlert(""{0}"");", message.Replace("\"", "'").Replace(Environment.NewLine, "\\n"));
            System.Web.UI.ScriptManager.RegisterStartupScript(this, this.GetType(), "", script, true);
        }

        /// <summary>
        /// Đăng ký script cho trang sau khi postback
        /// </summary>
        /// <param name="script"></param>
        public void RegisterStartUpScript(string script)
        {
            System.Web.UI.ScriptManager.RegisterStartupScript(this, this.GetType(), "", script, true);
        }

        /// <summary>
        /// Đăng ký script cho control nằm trong UpdatePanel
        /// </summary>
        /// <param name="script"></param>
        public void RegisterClientScriptBlock(string script)
        {
            System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "", script, true);
        }

        /// <summary>
        /// Kiểm tra tính hợp lệ của dữ liệu
        /// </summary>
        /// <returns></returns>
        protected virtual bool ValidateInfo()
        {
            return true;
        }

        /// <summary>
        /// Kiểm tra tính hợp lệ của dữ liệu
        /// </summary>
        /// <param name="entity">đối tượng được validate</param>
        /// <returns></returns>
        protected virtual bool ValidateInfo(object entity)
        {
            return true;
        }

        /// <summary>
        /// Kiểm tra tính hợp lệ của dữ liệu
        /// </summary>
        /// <param name="entity">đối tượng được validate</param>
        /// /// <param name="entity">đối tượng được validate</param>
        /// /// <param name="entityInfo">thông tin đối tượng được validate</param>
        /// <returns></returns>
        protected virtual bool ValidateInfo(object entity, object entityInfo)
        {
            return true;
        }

        //Function for File Download in ASP.Net in C# and 
        //Tracking the status of success/failure of Download.
        protected void DownloadFile_Tracking(string filePath)
        {
            System.IO.FileInfo FileName = new System.IO.FileInfo(filePath);
            //Reads file as binary values
            using (BinaryReader _BinaryReader = new BinaryReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
            {
                //Check whether file exists in specified location
                if (FileName.Exists)
                {
                    try
                    {
                        long startBytes = 0;
                        Response.Clear();
                        Response.Buffer = false;
                        Response.ContentType = "application/octet-stream";
                        Response.AddHeader("Content-Disposition", "attachment;filename=" + FileName.Name);
                        Response.AddHeader("Content-Length", (FileName.Length - startBytes).ToString());
                        Response.AddHeader("Connection", "Keep-Alive");
                        Response.ContentEncoding = Encoding.UTF8;

                        //Send data
                        _BinaryReader.BaseStream.Seek(startBytes, SeekOrigin.Begin);

                        //Dividing the data in 1024 bytes package
                        int maxCount = (int)Math.Ceiling((FileName.Length - startBytes + 0.0) / 1024);

                        //Download in block of 1024 bytes
                        int i;
                        for (i = 0; i < maxCount && Response.IsClientConnected; i++)
                        {
                            Response.BinaryWrite(_BinaryReader.ReadBytes(1024));
                            Response.Flush();
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        Response.End();
                    }
                }
                else
                    ShowMessageBox("Tệp tải về không tồn tại");
            }
        }

        /// <summary>
        /// Đổ dữ liệu cho DropdownList
        /// </summary>
        protected void BindDropDownListData(DropDownList ddl, object source, string datavalueField, string dataTextField)
        {
            ddl.DataSource = source;
            ddl.DataValueField = datavalueField;
            ddl.DataTextField = dataTextField;
            ddl.DataBind();
        }

        /// <summary>
        /// Đổ dữ liệu cho DropDownList và add thêm 1 ListItem lên top
        /// </summary>
        protected void BindDropDownListData(DropDownList ddl, object source, string datavalueField, string dataTextField, ListItem addtop)
        {
            BindDropDownListData(ddl, source, datavalueField, dataTextField);
            ddl.Items.Insert(0, addtop);
        }

        protected void BindListBoxData(ListBox lb, object source, string datavalueField, string dataTextField)
        {
            lb.DataSource = source;
            lb.DataValueField = datavalueField;
            lb.DataTextField = dataTextField;
            lb.DataBind();
        }

        protected void BindListBoxData(ListBox lb, object source, string datavalueField, string dataTextField, ListItem addtop)
        {
            BindListBoxData(lb, source, datavalueField, dataTextField);
            lb.Items.Insert(0, addtop);
        }
        #endregion

        #region Permission
        protected virtual bool IsRootAdmin()
        {
            if (UserID == null)
                return false;
            if (CurUser.UserName.Equals(Constants.AdminRootAccount, StringComparison.CurrentCultureIgnoreCase))
                return true;
            return false;
        }
        #endregion

        #region Privilege
        /// <summary>
        /// Kiểm tra quyền của link theo danh sách quyền được cung cấp
        /// </summary>
        /// <param name="roles">Danh sách quyền</param>
        /// <returns></returns>
        protected bool CheckRole(params string[] roles)
        {
            if (UserID == null)
                return false;
            if (IsRootAdmin())
                return true;
            return SysRole.CheckRole(UserID.Value, Request.RawUrl, roles);
        }

        /// <summary>
        /// Kiểm tra link có quyền truy nhập hay không
        /// </summary>
        /// <returns></returns>
        protected virtual bool HasRole()
        {
            return CheckRole(Role.Read, Role.Write);
        }
        
        /// <summary>
        /// Kiểm tra quyền của user đối với tên quyền. 
        /// Nếu không có quyền thì ném ra ngoại lệ
        /// </summary>
        protected virtual void Authorize(params string[] roles)
        {
            if(roles==null || roles.Length == 0)
                throw new CustomException("Bạn không có quyền thực hiện chức năng này");
            foreach (var role in roles)
            {
                if (!CheckRole(role))
                {
                    throw new CustomException("Bạn không có quyền thực hiện chức năng này");
                }
            }
        }

        protected virtual void HandleException(System.Runtime.InteropServices._Exception ex)
        {
            if (ex is CustomException)
            {
                ShowMessageBox(ex.Message);
                return;
            }
            else if (ex is Exception)
            {
                SysLog.InsertLog((Exception)ex);
                ShowMessageBox("Lỗi thao tác không toàn vẹn dữ liệu.\\nVui lòng kiểm tra tính hợp lệ của thao tác dữ liệu!");
                return;
            }
        }

        protected virtual void InsertChangeLog(string action)
        {
            if (UserID != null)
            {
                string ipAddress = "unknown";
                string hostName = "unknown";
                try
                {
                    ipAddress = Request.UserHostAddress;
                    SysChangeLog.Insert(UserID.Value, action, hostName, ipAddress);
                }
                catch
                {
                    SysChangeLog.Insert(UserID.Value, action, hostName, ipAddress);
                }
            }
        }

        protected static void SInsertChangeLog(string action)
        {
            int UserID = int.Parse(HttpContext.Current.User.Identity.Name);
            string ipAddress = "unknown";
            string hostName = "unknown";
            try
            {
                ipAddress = HttpContext.Current.Request.UserHostAddress;
                SysChangeLog.Insert(UserID, action, hostName, ipAddress);
            }
            catch
            {
                SysChangeLog.Insert(UserID, action, hostName, ipAddress);
            }
        }

        public static bool SAuthorize(string role)
        {
            try
            {
                SysUser currUser = SysUser.GetByID(int.Parse(HttpContext.Current.User.Identity.Name));
                if (currUser != null)
                {
                    if (currUser.UserName.Equals(Constants.AdminRootAccount, StringComparison.CurrentCultureIgnoreCase))
                        return true;
                    return SysRole.CheckRole(currUser.UserID, HttpContext.Current.Request.RawUrl, role);
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        #endregion
    }


    public class SESSION
    {
        public const string USER_NAME = "vEfBd0wspB9/o3Im68sjGVzBeT1pNda2+tfIJLzjAbM=";
        public const string RETURN_URL = "ReturnURL";
        public const string PostID = "PostID";
        public const string PageSize = "PageSize";
        public const string ActiveLink = "ActiveLink";
        public const string NeedReloadMenu = "NeedReloadMenu";
    }

    public class COOKIES
    {
        public const string LOGIN = "Anuntiomatic.Server.LOGIN";//"so2LOqEnx+iZA9z6gM3DnC4zqDnV1aQt6gMEoyT9VPY=";
        public const string USERNAME = "Anuntiomatic.Server.USERNAME";//"uYmJn2HSS13Xlmfg9MgATtiFwiLt+9uTy71YLErxQCo=";
        public const string PASSWORD = "Anuntiomatic.Server.PASSWORD";//"jcmYRihD98V9mP9q0LIrllv8+4KyhM4ESS4wtIYSZyM=";
    }

    public class Role
    {
        public const string Admin = "Admin";
        public const string Read = "Read";
        public const string Write = "Write";
        public const string Export = "Export";
        public const string Approve = "Approve";
        public const string Download = "Download";
        public const string Recusive = "Recusive";
    }
}